#ifndef _profile_h_INCLUDED
#define _profile_h_INCLUDED

#ifndef QUIET

#include "stack.h"

typedef struct profile profile;
typedef struct profiles profiles;

#define PROFS                                                                                                          \
	PROF(analyze, 3)                                                                                                   \
	PROF(autarky, 2)                                                                                                   \
	PROF(backward, 4)                                                                                                  \
	PROF(bump, 3)                                                                                                      \
	PROF(collect, 3)                                                                                                   \
	PROF(decide, 4)                                                                                                    \
	PROF(deduce, 3)                                                                                                    \
	PROF(defrag, 3)                                                                                                    \
	PROF(eliminate, 2)                                                                                                 \
	PROF(extend, 2)                                                                                                    \
	PROF(failed, 2)                                                                                                    \
	PROF(focused, 2)                                                                                                   \
	PROF(forward, 4)                                                                                                   \
	PROF(minimize, 3)                                                                                                  \
	PROF(parse, 1)                                                                                                     \
	PROF(probe, 2)                                                                                                     \
	PROF(propagate, 4)                                                                                                 \
	PROF(radix, 4)                                                                                                     \
	PROF(reduce, 2)                                                                                                    \
	PROF(rephase, 3)                                                                                                   \
	PROF(restart, 3)                                                                                                   \
	PROF(search, 1)                                                                                                    \
	PROF(simplify, 1)                                                                                                  \
	PROF(sort, 4)                                                                                                      \
	PROF(stable, 2)                                                                                                    \
	PROF(substitute, 2)                                                                                                \
	PROF(subsume, 2)                                                                                                   \
	PROF(ternary, 2)                                                                                                   \
	PROF(total, 0)                                                                                                     \
	PROF(transitive, 2)                                                                                                \
	PROF(vivify, 2)                                                                                                    \
	PROF(walking, 2)

struct profile
{
	int level;
	const char* name;
	double entered;
	double time;
};

struct profiles
{
#define PROF(NAME, LEVEL) profile NAME;
	PROFS
#undef PROF
	STACK(profile*) stack;
};

struct kissat;

void
kissat_mab_init_profiles(profiles*);
void
kissat_mab_profiles_print(struct kissat*);
void
kissat_mab_start(struct kissat*, profile*);
void
kissat_mab_stop(struct kissat*, profile*);

void
kissat_mab_stop_search_and_start_simplifier(struct kissat*, profile*);
void
kissat_mab_stop_simplifier_and_resume_search(struct kissat*, profile*);

double
kissat_mab_time(struct kissat*);

#define PROFILE(NAME) (solver->profiles.NAME)

#define START(NAME)                                                                                                    \
	do {                                                                                                               \
		profile* profile = &PROFILE(NAME);                                                                             \
		if (GET_OPTION(profile) >= profile->level)                                                                     \
			kissat_mab_start(solver, profile);                                                                         \
	} while (0)

#define STOP(NAME)                                                                                                     \
	do {                                                                                                               \
		profile* profile = &PROFILE(NAME);                                                                             \
		if (GET_OPTION(profile) >= profile->level)                                                                     \
			kissat_mab_stop(solver, profile);                                                                          \
	} while (0)

#define STOP_SEARCH_AND_START_SIMPLIFIER(NAME)                                                                         \
	do {                                                                                                               \
		if (GET_OPTION(profile) >= PROFILE(search).level)                                                              \
			kissat_mab_stop_search_and_start_simplifier(solver, &PROFILE(NAME));                                       \
	} while (0)

#define STOP_SIMPLIFIER_AND_RESUME_SEARCH(NAME)                                                                        \
	do {                                                                                                               \
		if (GET_OPTION(profile) >= PROFILE(search).level)                                                              \
			kissat_mab_stop_simplifier_and_resume_search(solver, &PROFILE(NAME));                                      \
	} while (0)

#else

#define START(...)                                                                                                     \
	do {                                                                                                               \
	} while (0)
#define STOP(...)                                                                                                      \
	do {                                                                                                               \
	} while (0)

#define STOP_SEARCH_AND_START_SIMPLIFIER(...)                                                                          \
	do {                                                                                                               \
	} while (0)
#define STOP_SIMPLIFIER_AND_RESUME_SEARCH(...)                                                                         \
	do {                                                                                                               \
	} while (0)

#define STOP_AND_START(...)                                                                                            \
	do {                                                                                                               \
	} while (0)

#endif

#endif
